`timescale 1ns / 1ps
`include "defines2.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2017/11/02 14:52:16
// Design Name: 
// Module Name: alu
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module alu(
	input wire[31:0] a,b,
	input wire[4:0] op,
	input wire[4:0] sa,
	output reg[31:0] y,
	output reg overflow,
	output wire zero
    );

	wire [32:0] a1,b1,addy,suby;
	assign a1={1'b0,a};
	assign b1={1'b0,b};
	assign addy=a1+b1;
	assign suby=a1-b1;

	always @(*) begin
		case (op)
			//逻辑指令
			`AND_CONTROL : y <= a & b;
			`OR_CONTROL : y <= a|b;
			`XOR_CONTROL : y <= a^b;
			`NOR_CONTROL : y <= ~(a|b);
			`LUI_CONTROL : y<={b[15:0],16'b0};

			`SLL_CONTROL : y <= b <<sa;
			`SRL_CONTROL : y <= b >> sa;
			`SRA_CONTROL : y <= ({32{b[31]}} << (6'd32-{1'b0,sa})) | b >> sa;
			`SLLV_CONTROL : y <= b << a[4:0];
			`SRLV_CONTROL : y <= b >> a[4:0];
			`SRAV_CONTROL : y <= ({32{b[31]}} << (6'd32-{1'b0,a[4:0]})) | b >> a[4:0];

			// 数据移动指令
			`MFHI_CONTROL: y <= a + b;
			`MFLO_CONTROL: y <= a + b;
			// 存hilo寄存器不用其他计算
			`MTHI_CONTROL : y <= 32'b0;
			`MTLO_CONTROL : y <= 32'b0;
			//算数指令
			`ADD_CONTROL: y<=a+b;
			`ADDU_CONTROL : y<=addy[31:0];
			`SUB_CONTROL : y<=a-b;
			`SUBU_CONTROL : y<=suby[31:0];
			`SLT_CONTROL : y<=(a[31]&!b[31])?1:
                              ((!a[31])&b[31])?0:
                        	  (a<b);
			`SLTU_CONTROL : y<=(suby[32]==1)?1:0;//?

			default : y <= 32'b0;
		endcase	
	end
	assign zero = (y == 32'b0);





	// wire[31:0] s,bout;
	// assign bout = op[2] ? ~b : b;
	// assign s = a + bout + op[2];
	// always @(*) begin
	// 	case (op[1:0])
	// 		2'b00: y <= a & bout;
	// 		2'b01: y <= a | bout;
	// 		2'b10: y <= s;
	// 		2'b11: y <= s[31];
	// 		default : y <= 32'b0;
	// 	endcase	
	// end
	// assign zero = (y == 32'b0);

	// always @(*) begin
	// 	case (op[2:1])
	// 		2'b01:overflow <= a[31] & b[31] & ~s[31] |
	// 						~a[31] & ~b[31] & s[31];
	// 		2'b11:overflow <= ~a[31] & b[31] & s[31] |
	// 						a[31] & ~b[31] & ~s[31];
	// 		default : overflow <= 1'b0;
	// 	endcase	
	// end
endmodule
